import re, hashlib, random
from types import *
from google.appengine.api import xmpp
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app


class XMPPHandler( webapp.RequestHandler ):
    def post( self ):
        msg = xmpp.Message( self.request.POST )
        msg.reply( "%s Rolled: %s" % ( msg.sender, Dice_O_Matic( msg.body ).result ) )

class Dice_O_Matic:

    def __init__( self, input ):
        self.op = {
            "+"  : self.do_add,
            "-"  : self.do_sub,
            "*"  : self.do_mul,
            "/"  : self.do_div,
            "d"  : self.do_roll,
            "c!" : self.for_cortex,
            ">"  : self.get_above,
            "<"  : self.get_below,
            ">>" : self.get_highest,
            "<<" : self.get_lowest
        }
        p = re.compile(r"d|\d+|\+|\-|\*|\/|\=|\>{1,2}|\<{1,2}|c\!")
        self.result = self.format_numbers( p.findall( input ) )
        self.input = input
        self.do_ops( "d|\>{1,2}|\<{1,2}" )
        self.do_ops( "\*|\/" )
        self.do_ops( "\+|\-" )
        self.do_ops( "c\!" )
    #def on( input ):
        

    def format_numbers( self, input ):
        output = [] # create output list
        numbers = [] # create numbers list
        for v in input: # go through every element in the input list
            if re.match("\d+", v): # and when you encounter a number
                numbers.append(int(v)) # add it to the numbers list
            else: # and when you encounter an operand, take the output list
                output.append(numbers) # and append the numbers list
                output.append(v) # then append the operand
                numbers = [] # and reset the numbers list
        output.append(numbers) # append the numbers list to the output list
        return output

    def do_ops( self, pattern ):
        ops = re.compile( pattern ).findall( self.input )
        for op in ops:
            i = self.result.index( op )
            self.result[i-1:i+2] = self.op[ op ]( self.result, i )

    def do_add(self, d, i):
        d[i-1].extend(d[i+1]) # append the two lists
        return [sum( d[i-1] )] # and return the sum of their contents in a list
    def do_sub(self, d, i):
        return [sum( d[i-1] ) - sum( d[i+1] )]
    def do_mul(self, d, i):
        return [int(d[i-1]) * int(d[i+1])]
    def do_div(self, d, i):
        return [int(d[i-1]) / int(d[i+1])]
    def do_roll(self, d, i):
        results = [random.randrange(1, d[i+1][0]+1 ) for ii in range( d[i-1][0] )]
        results.sort()
        return [results]
    def for_cortex(self, d, i):
        results = [ random.randrange( 1, v+1 ) for v in d[i-1] ]
        ones = [ v for v in zip( d[i-1], results ) if v[1] < 2 ]
        two_highest = d[i-1][:2]
        return [sum(two_highest), ones]
    def get_above(self, d, i):
        return [ v for v in d[i-1] if v > d[i+1][0] ]
    def get_below(self, d, i):
        return [ v for v in d[i-1] if v < d[i+1][0] ]
    def get_highest(self, d, i):
        d[i-1].reverse()
        r = d[i-1][:d[i+1][0]]
        return [r]
    def get_lowest(self, d, i):
        r = d[i-1][:d[i+1][0]]
        return [r]

application = webapp.WSGIApplication([
    ('/_ah/xmpp/message/chat/', XMPPHandler)
], debug=True)


def main():
    run_wsgi_app(application)


if __name__ == '__main__':
    main()